package com.wanhe.qrcode;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.TextView;
import android.widget.Toast;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.RGBLuminanceSource;
import com.google.zxing.Result;
import com.google.zxing.ResultPoint;
import com.google.zxing.client.result.ResultParser;
import com.google.zxing.common.HybridBinarizer;

import java.io.IOException;
import java.util.Collection;

/**
 * 扫描并可以处理二维码的Activity
 * 
 * @author xiezw
 * 
 * 
 */
public final class CaptureActivity extends Activity implements SurfaceHolder.Callback, View.OnClickListener {

	private static final long BULK_MODE_SCAN_DELAY_MS = 1000L;
	public static final int HISTORY_REQUEST_CODE = 0x0000bacc;
	private CameraManager cameraManager;
	private CaptureActivityHandler handler;
	private Result savedResultToShow;
	private ViewfinderView viewfinderView;
	private TextView statusView;
	private Result lastResult;
	private boolean hasSurface;
	private Collection<BarcodeFormat> decodeFormats;
	private String characterSet;
	private BeepManager beepManager;

	private final int PHOTO_PICKED = 2;

	ViewfinderView getViewfinderView() {
		return viewfinderView;
	}

	public Handler getHandler() {
		return handler;
	}

	CameraManager getCameraManager() {
		return cameraManager;
	}

	public static void startCaptureActivity(Activity act) {
		Intent intent = new Intent(act, CaptureActivity.class);
		act.startActivity(intent);
	}

	@Override
	public void onCreate(Bundle icicle) {
		super.onCreate(icicle);
		if (!QRCodeUtil.hasCamera(this)) {
			Toast.makeText(this, R.string.err_txt_withoutcamera, Toast.LENGTH_SHORT).show();
			finish();
			return;
		}
		Window window = getWindow();
		window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
		setContentView(R.layout.capture_activity);
		initView();

		hasSurface = false;
		beepManager = new BeepManager(this);

	}

	private void initView() {
		TextView title_bar_title = (TextView) findViewById(R.id.tv_title);
		title_bar_title.setText(R.string.qr_code);

		findViewById(R.id.lin_albums).setOnClickListener(this);
		findViewById(R.id.iv_back).setOnClickListener(this);
	}

	@Override
	protected void onResume() {
		super.onResume();

		cameraManager = new CameraManager(getApplication());

		viewfinderView = (ViewfinderView) findViewById(R.id.viewfinder_view);
		viewfinderView.setCameraManager(cameraManager);

		statusView = (TextView) findViewById(R.id.status_view);

		handler = null;
		lastResult = null;

		resetStatusView();

		SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview_view);
		SurfaceHolder surfaceHolder = surfaceView.getHolder();
		if (hasSurface) {
			// The activity was paused but not stopped, so the surface still
			// exists. Therefore
			// surfaceCreated() won't be called, so init the camera here.
			initCamera(surfaceHolder);
		} else {
			// Install the callback and wait for surfaceCreated() to init the
			// camera.
			surfaceHolder.addCallback(this);
			surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
		}
		beepManager.updatePrefs(); // 设置震动
		decodeFormats = null;
		characterSet = null;
	}

	@Override
	protected void onPause() {
		if (handler != null) {
			handler.quitSynchronously();
			handler = null;
		}
		cameraManager.closeDriver();
		if (!hasSurface) {
			SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview_view);
			SurfaceHolder surfaceHolder = surfaceView.getHolder();
			surfaceHolder.removeCallback(this);
		}
		super.onPause();
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if (keyCode == KeyEvent.KEYCODE_BACK) {
			if (lastResult != null) {
				// restartPreviewAfterDelay(0L);
				finish();
				return true;
			}
		} else if (keyCode == KeyEvent.KEYCODE_FOCUS || keyCode == KeyEvent.KEYCODE_CAMERA) {
			// Handle these events so they don't launch the Camera app
			return true;
		}
		return super.onKeyDown(keyCode, event);
	}

	private void decodeOrStoreSavedBitmap(Bitmap bitmap, Result result) {
		// Bitmap isn't used yet -- will be used soon
		if (handler == null) {
			savedResultToShow = result;
		} else {
			if (result != null) {
				savedResultToShow = result;
			}
			if (savedResultToShow != null) {
				Message message = Message.obtain(handler, R.id.decode_succeeded, savedResultToShow);
				handler.sendMessage(message);
			}
			savedResultToShow = null;
		}
	}

	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		if (!hasSurface) {
			hasSurface = true;
			initCamera(holder);
		}
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {
		hasSurface = false;
	}

	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

	}

	/**
	 * A valid barcode has been found, so give an indication of success and show
	 * the results.
	 * 
	 * @param rawResult
	 *            The contents of the barcode.
	 * @param barcode
	 *            A greyscale bitmap of the camera data which was decoded.
	 */
	public void handleDecode(Result rawResult, Bitmap barcode) {
		lastResult = rawResult;

		URIResultHandler resultHandler = new URIResultHandler(this, ResultParser.parseResult(rawResult));

		if (barcode == null) {
			// This is from history -- no saved barcode
			handleDecodeInternally(rawResult, resultHandler, null);
		} else {
			beepManager.playBeepSoundAndVibrate();
			drawResultPoints(barcode, rawResult);
			if (PreferenceConfig.KEY_BULK_MODE_ENABLE) {
				// Wait a moment or else it will scan the same barcode
				// continuously about 3 times
				restartPreviewAfterDelay(BULK_MODE_SCAN_DELAY_MS);
			} else {
				handleDecodeInternally(rawResult, resultHandler, barcode);
			}
		}
	}

	/**
	 * Superimpose a line for 1D or dots for 2D to highlight the key features of
	 * the barcode.
	 * 
	 * @param barcode
	 *            A bitmap of the captured image.
	 * @param rawResult
	 *            The decoded results which contains the points to draw.
	 */
	private void drawResultPoints(Bitmap barcode, Result rawResult) {
		ResultPoint[] points = rawResult.getResultPoints();
		if (points != null && points.length > 0) {
			Canvas canvas = new Canvas(barcode);
			Paint paint = new Paint();
			paint.setColor(getResources().getColor(R.color.result_image_border));
			paint.setStrokeWidth(3.0f);
			paint.setStyle(Paint.Style.STROKE);
			Rect border = new Rect(2, 2, barcode.getWidth() - 2, barcode.getHeight() - 2);
			canvas.drawRect(border, paint);

			paint.setColor(getResources().getColor(R.color.result_points));
			if (points.length == 2) {
				paint.setStrokeWidth(4.0f);
				drawLine(canvas, paint, points[0], points[1]);
			} else if (points.length == 4 &&
					(rawResult.getBarcodeFormat() == BarcodeFormat.UPC_A ||
					rawResult.getBarcodeFormat() == BarcodeFormat.EAN_13)) {
				// Hacky special case -- draw two lines, for the barcode and
				// metadata
				drawLine(canvas, paint, points[0], points[1]);
				drawLine(canvas, paint, points[2], points[3]);
			} else {
				paint.setStrokeWidth(10.0f);
				for (ResultPoint point : points) {
					canvas.drawPoint(point.getX(), point.getY(), paint);
				}
			}
		}
	}

	private static void drawLine(Canvas canvas, Paint paint, ResultPoint a, ResultPoint b) {
		canvas.drawLine(a.getX(), a.getY(), b.getX(), b.getY(), paint);
	}

	private void showResult(Result rawResult, URIResultHandler resultHandler, Bitmap barcode) {
		CharSequence displayContents = resultHandler.getDisplayContents();
		String qrString = displayContents.toString();
		dealQRString(qrString);

	}

	private void dealQRString(String qrString) {
		// QRShowTextActivity.startQRShowTextActivity(this, qrString);
//		MatchDetailActivity.startMatchDetailActivity(this, MatchDetailActivity.TYPE_REGISTERING);
		System.out.println("===dealQRString==" + qrString);
		QRWebViewActivity.startQRWebViewActivity(this, qrString);
		// if (qrString.startsWith(GlobalConst.QR_CODE_DOWNLOAD_URL)) {
		// qrString = qrString.split(GlobalConst.QR_CODE_DOWNLOAD_URL)[1];
		// qrString = qrString.substring(2);
		// qrString = AESCrypto.decrypt(qrString);
		// String[] results = qrString.split("=");
		//
		// if ("linkp".equals(results[0])) {
		// qrString = results[1];
		// ProfileMng.startProfileActivity(this, qrString, true,
		// Friend.IGG_FRIENDSOURCE_QRCODE, "");
		//
		// } else if ("linkg".equals(results[0])) {
		// qrString = results[1];
		// ProfileMng.startProfileActivity(this, qrString, "");
		// }
		// finish();
		// CrashLogHttp.collectUserBehavior(CrashLogHttp.USER_BEHAVIOR_104020203);
		//
		// } else if (Utils.isURL(qrString)) {
		// // BrowserWebActivity.startBrowserWebActivity(this, "", qrString);
		// ShowInWebActivity.startShowInWebActivity(this, qrString, "");
		//
		// } else {
		// QRShowTextActivity.startQRShowTextActivity(this, qrString);
		// }

	}

	private void handleDecodeInternally(Result rawResult, URIResultHandler resultHandler, Bitmap barcode) {
		statusView.setVisibility(View.GONE);
		viewfinderView.setVisibility(View.GONE);
		showResult(rawResult, resultHandler, barcode);
	}

	private void initCamera(SurfaceHolder surfaceHolder) {
		try {
			cameraManager.openDriver(surfaceHolder);
			if (handler == null) {
				handler = new CaptureActivityHandler(this, decodeFormats, characterSet, cameraManager);
			}
			decodeOrStoreSavedBitmap(null, null);
		} catch (IOException ioe) {
			ioe.printStackTrace();
			displayFrameworkBugMessageAndExit();
		} catch (RuntimeException e) {
			e.printStackTrace();
			displayFrameworkBugMessageAndExit();
		} catch (Exception e) {
			e.printStackTrace();
			displayFrameworkBugMessageAndExit();
		}
	}

	private void displayFrameworkBugMessageAndExit() {
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setTitle(getString(R.string.app_name));
		builder.setMessage(getString(R.string.qrcode_txt_camerabug));
		builder.setPositiveButton(R.string.txt_ok, new OnClickListener() {

			@Override
			public void onClick(DialogInterface dialog, int which) {
				finish();
			}
		});
		builder.setOnCancelListener(new OnCancelListener() {

			@Override
			public void onCancel(DialogInterface dialog) {
				finish();
			}
		});
		builder.show();
	}

	public void restartPreviewAfterDelay(long delayMS) {
		if (handler != null) {
			handler.sendEmptyMessageDelayed(R.id.restart_preview, delayMS);
		}
		resetStatusView();
	}

	private void resetStatusView() {
		statusView.setText(R.string.post_photo_album);
		statusView.setVisibility(View.VISIBLE);
		viewfinderView.setVisibility(View.VISIBLE);
		lastResult = null;
	}

	public void drawViewfinder() {
		viewfinderView.drawViewfinder();
	}

	protected Result scanningImage(String path) {
		if (TextUtils.isEmpty(path)) {
			return null;
		}
		Bitmap scanBitmap = null;
		BitmapFactory.Options options = new BitmapFactory.Options();
		options.inPreferredConfig = Bitmap.Config.RGB_565;

		try {
			scanBitmap = BitmapFactory.decodeFile(path, options);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}

		scanBitmap = QRCodeUtil.RotateBitmap(scanBitmap, 90);
		int width = scanBitmap.getWidth();
		int height = scanBitmap.getHeight();
		int[] pixels = new int[width * height];
		scanBitmap.getPixels(pixels, 0, width, 0, 0, width, height);
		scanBitmap.recycle();
		scanBitmap = null;
		RGBLuminanceSource source = new RGBLuminanceSource(width, height, pixels);
		BinaryBitmap bBitmap = new BinaryBitmap(new HybridBinarizer(source));
		MultiFormatReader reader = new MultiFormatReader();
		try {
			Result result = reader.decode(bBitmap);
			return result;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}

	}

	@Override
	public void onClick(View v) {
		int id = v.getId();
		if(id == R.id.iv_back){
			finish();
		}
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent paramIntent) {
		if (resultCode == RESULT_OK) {
			switch (requestCode) {
			case PHOTO_PICKED:

				// String tPath = "";
				// int pSize = SelectedPhotosMng.getInstance().getCount();
				// if (pSize > 0) {
				// SelectPhotoBean sPhoto =
				// SelectedPhotosMng.getInstance().getItem(0);
				// if (null != sPhoto) {
				// tPath = sPhoto.imagePath;
				// }
				// } else {
				// SelectedPhotosMng.getInstance().clearData();
				// return;
				// }
				// SelectedPhotosMng.getInstance().clearData();
				//
				// Result result = scanningImage(tPath);
				// if (result != null) {
				// tPath = result.toString();
				// dealQRString(tPath);
				// } else {
				// Toast.makeText(this, R.string.addfriend_txt_QRcode_wrong,
				// Toast.LENGTH_LONG).show();
				// }

				break;

			default:
				break;
			}

		}

	}

}
